package com.share.thread.future;

import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.stream.IntStream;

/**
 * @author caifan
 * @since 2022/6/22
 */
public class CompletableFutureDemo01 {

    public static void main(String[] args) {
        System.out.println(thenApplyTest());
        System.out.println(applyToEitherTest());
        thenAcceptBothTest();
        runAfterBoth();
        exceptionTest();
        // 异常有返回异常信息
        exceptionTest01();
        // 异常无返回值
        exceptionTest02();
    }

    private static String thenApplyTest() {
        CompletableFuture<String> thenApply = CompletableFuture.supplyAsync(() -> "Hello Java")   // 异步
                .thenApply(s -> s + " 支付宝") // 异步之后 函数接口
                .thenApply(String::toUpperCase);//

        return thenApply.join();
    }

    /**
     * 两个异步线程执行完获取最后结果
     */
    private static void thenAcceptBothTest() {
        CompletableFuture<String> book = CompletableFuture.supplyAsync(() -> "this is book");
        CompletableFuture<Integer> price = CompletableFuture.supplyAsync(() -> 35);

        book.thenAcceptBoth(price, (b, p) -> System.out.println(b + ":" + p));
        // 等价于上面一行代码
        book.thenAcceptBoth(price, new BiConsumer<String, Integer>() {
            @Override
            public void accept(String s, Integer integer) {
                System.out.println(s + ":" + integer);
            }
        });
    }

    /**
     * runAfterBoth第二个参数是 Runable，这里可以 CyclicBarrier带参
     */
    private static void runAfterBoth() {
        CompletableFuture<String> eat = CompletableFuture.supplyAsync(() -> "吃饭");
        CompletableFuture<String> work = CompletableFuture.supplyAsync(() -> "工作");
        eat.runAfterBothAsync(work, () -> {
            System.out.println("下班了");
        });
    }

    /**
     * 两个任务只要有一个执行完即可
     * @return
     */
    private static Integer applyToEitherTest() {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
            int t = IntStream.range(1, 10).sum();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return t;
        });

        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
            int t = IntStream.range(5, 10).sum();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return t;
        });

        CompletableFuture<Integer> f3 = f1.applyToEither(f2, s -> s);
        return f3.join();
    }

    /**
     * 异常处理
     */
    private static void exceptionTest() {
        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> 7 / 0)
                .thenApply(r -> r * 10)
                .exceptionally(e -> 0); // 存在异常则返回0
        System.out.println(f.join());
    }

    /**
     * 异常信息返回
     */
    private static void exceptionTest01() {
        CompletableFuture<Throwable> f = CompletableFuture.supplyAsync(() -> 7 / 0)
                .thenApply(r -> r * 3)
                .handle((__, b) -> { // __表示Void 此处有异常则返回值为null或者指定值
                    System.out.println(1);
                    return b;
                });
        System.out.println(f.join());
    }

    private static void exceptionTest02() {
        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> 7 / 0)
                .thenApply(r -> r * 3)
                .whenComplete((k, v) -> { // whenComplete相比 上面 handle是无返回值
                    System.out.println(k + ":" + v);
                });
        System.out.println(f.join());
    }
}

